/* example1.c                                                      */
/*                                                                 */
/* This small program shows how to print a rotated string with the */
/* FreeType 2 library.                                             */

#include "ft2build.h"
#include FT_FREETYPE_H

#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include <math.h>
#include <iostream>


#define WIDTH   640
#define HEIGHT  480
#define ET_SIZE 300
char errorText[ET_SIZE];

/* origin is the upper left corner */
unsigned char image[HEIGHT][WIDTH];


void errorMsg(const char *msg)
{
    printf("error:%s\n", msg);
    exit(-1);

}
/* Replace this function with something useful. */

void
draw_bitmap( FT_Bitmap*  bitmap,
             FT_Int      x,
             FT_Int      y)
{
  FT_Int  i, j, p, q;
  FT_Int  x_max = x + bitmap->width;
  FT_Int  y_max = y + bitmap->rows;


  /* for simplicity, we assume that `bitmap->pixel_mode' */
  /* is `FT_PIXEL_MODE_GRAY' (i.e., not a bitmap font)   */

  for ( i = x, p = 0; i < x_max; i++, p++ )
  {
    for ( j = y, q = 0; j < y_max; j++, q++ )
    {
      if ( i < 0      || j < 0       ||
           i >= WIDTH || j >= HEIGHT )
        continue;

      image[j][i] |= bitmap->buffer[q * bitmap->width + p];
    }
  }
}

//
void write_bmpheader(unsigned char *bitmap, int offset, int bytes, int value)
{
    int i;
    for (i = 0; i < bytes; i++)
        bitmap[offset + i] = (value >> (i << 3)) & 0xFF;
}

unsigned char *convertToBmp(unsigned char inputImg[HEIGHT][WIDTH], int width, int height, int *ouputSize)
{
    /*create a bmp format file*/
    int bitmap_x = (int)ceil((double)width * 3 / 4) * 4;
    unsigned char *bitmap = (unsigned char*)malloc(sizeof(unsigned char)*height*bitmap_x + 54);

    bitmap[0] = 'B';
    bitmap[1] = 'M';
    write_bmpheader(bitmap, 2, 4, height*bitmap_x + 54); //whole file size
    write_bmpheader(bitmap, 0xA, 4, 54); //offset before bitmap raw data
    write_bmpheader(bitmap, 0xE, 4, 40); //length of bitmap info header
    write_bmpheader(bitmap, 0x12, 4, width); //width
    write_bmpheader(bitmap, 0x16, 4, height); //height
    write_bmpheader(bitmap, 0x1A, 2, 1);
    write_bmpheader(bitmap, 0x1C, 2, 24); //bit per pixel
    write_bmpheader(bitmap, 0x1E, 4, 0); //compression
    write_bmpheader(bitmap, 0x22, 4, height*bitmap_x); //size of bitmap raw data

    for (int i = 0x26; i < 0x36; i++)
        bitmap[i] = 0;

    int k = 54;
    for (int i = height - 1; i >= 0; i--) {
        int j;
        for (j = 0; j < width; j++) {
            int index = i*width + j;
            for (int l = 0; l < 3; l++)
                bitmap[k++] = inputImg[i][j];
        }
        j *= 3;
        while (j < bitmap_x) {
            bitmap[k++] = 0;
            j++;
        }
    }
    *ouputSize = k;
    return bitmap;
}

void saveToBmp(unsigned char inputImg[HEIGHT][WIDTH], int width, int height, char *outputFileName)
{
    int size;
    unsigned char *bmp = convertToBmp(inputImg, width, height, &size);
    FILE *fp = fopen(outputFileName, "wb+");
    if (fp == NULL) {
        sprintf(errorText, "Could not open file: %s", outputFileName);
        errorMsg(errorText);

    }
    fwrite(bmp, 1, size, fp);
    fclose(fp);
    free(bmp);
}


//

int
main( int     argc,
      char**  argv )
{
  FT_Library    library;
  FT_Face       face;

  FT_GlyphSlot  slot;
  FT_Matrix     matrix;                 /* transformation matrix */
  FT_Vector     pen;                    /* untransformed origin  */
  FT_Error      error;

  char*         filename;
  char*         text;

  double        angle;
  int           target_height;
  size_t        n, num_chars;

  if (argc < 2) {
    fprintf(stderr, "Usage: %s FONT\n", argv[0]);
    return EXIT_FAILURE;
  }

  filename      = argv[1];
  text          = "conan-center-index";
  num_chars     = strlen( text );
  angle         = ( 25.0 / 360 ) * 3.14159 * 2;      /* use 25 degrees     */
  target_height = HEIGHT;

  error = FT_Init_FreeType( &library );              /* initialize library */
  if (error) {
      exit(EXIT_FAILURE);
  }

  error = FT_New_Face( library, filename, 0, &face );/* create face object */
  if (error) {
      exit(EXIT_FAILURE);
  }

  /* use 50pt at 100dpi */
  error = FT_Set_Char_Size( face, 30 * 64, 0, 100, 0 );
  if (error) {
      exit(EXIT_FAILURE);
  }

  /* cmap selection omitted;                                        */
  /* for simplicity we assume that the font contains a Unicode cmap */

  slot = face->glyph;

  /* set up matrix */
  matrix.xx = (FT_Fixed)( cos( angle ) * 0x10000L );
  matrix.xy = (FT_Fixed)(-sin( angle ) * 0x10000L );
  matrix.yx = (FT_Fixed)( sin( angle ) * 0x10000L );
  matrix.yy = (FT_Fixed)( cos( angle ) * 0x10000L );

  /* the pen position in 26.6 cartesian space coordinates; */
  /* start at (300,200) relative to the upper left corner  */
  pen.x = 300 * 64;
  pen.y = ( target_height - 200 ) * 64;

  for ( n = 0; n < num_chars; n++ )
  {
    /* set transformation */
    FT_Set_Transform( face, &matrix, &pen );

    /* load glyph image into the slot (erase previous one) */
    error = FT_Load_Char( face, text[n], FT_LOAD_RENDER);
    if (error) {
        exit(EXIT_FAILURE);
    }

    /* now, draw to our target surface (convert position) */
    draw_bitmap( &slot->bitmap,
                 slot->bitmap_left,
                 target_height - slot->bitmap_top );
    
    
    /* increment pen position */
    pen.x += slot->advance.x;
    pen.y += slot->advance.y;
  }
  saveToBmp(image, WIDTH, HEIGHT, "freetype.bmp");

  FT_Done_Face    ( face );
  FT_Done_FreeType( library );


  return EXIT_SUCCESS;
}

/* EOF */
